package com.bootcamp.javase2.threads;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;

/**
 * @program: ThreadCode
 * @description: force crack a password and store the password used.
 * @author: Keyu Li
 * @create: 2021-09-13 20:25
 **/

public class ForceCrackDemo {
    static final int PASS_BOUND = 1000;

    public static void main(String[] args) {
        // get random password
        Random rd = new Random();
        CrackThread ctM = new CrackThread("crackThread", rd.nextInt(PASS_BOUND));
        LogPasswordDaemon lpd = new LogPasswordDaemon("logDeamon");
        ctM.setLpd(lpd);
        lpd.setCt(ctM);
        lpd.setDaemon(true);
        ctM.start();
        lpd.start();

    }
}

class CrackThread extends Thread {
    private int[] passInvalid = new int[ForceCrackDemo.PASS_BOUND];
    private int passNum;
    int pass;
    boolean crackSucceed = false;
    LogPasswordDaemon lpd;

    public void setLpd(LogPasswordDaemon lpd) {
        this.lpd = lpd;
    }

    // store password in an array.
    public int[] getPassInvalid() {
        return passInvalid;
    }

    public int getPassNum() {
        return passNum;
    }

    public boolean isCrackSucceed() {
        return crackSucceed;
    }

    public CrackThread(String name, int pass) {
        super(name);
        this.pass = pass;
    }

    public int getPass() {
        return pass;
    }

    @Override
    public void run() {
        System.out.println(pass);
        try {
            for (int i = 0; i < ForceCrackDemo.PASS_BOUND; i++) {
                if (i == pass) break;
                passInvalid[i] = i;
                passNum++;
                Thread.sleep(1);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        crackSucceed = true;
        System.out.println(getName() + " crack succeed!!!");
        while (!lpd.isWriteSucceed()) {
        }
    }
}

class LogPasswordDaemon extends Thread {

    CrackThread ct;
    int count;
    boolean writeSucceed = false;

    public LogPasswordDaemon(String name) {
        super(name);
    }

    public boolean isWriteSucceed() {
        return writeSucceed;
    }

    public void setCt(CrackThread ct) {
        this.ct = ct;
    }

    @Override
    public void run() {
        try {
            FileWriter writer = new FileWriter("a.java", true);
            writer.write("the password is: " + ct.getPass() + System.lineSeparator());
            while (!ct.isCrackSucceed()) {
                int bound = ct.getPassNum();
//                System.out.println("count:"+count+" bound:"+bound);
                while (count < bound) {
                    System.out.println("count:" + count + " bound:" + bound);
                    writer.write(String.valueOf(ct.getPassInvalid()[count++]) + ", ");
                    if (count % 20 == 0)
                        writer.write(System.lineSeparator());
                    writer.flush();
                }
            }
            writer.write(System.lineSeparator());
            writer.close();
            System.out.println(getName() + " store invalid password succeed!!!");
        } catch (IOException e) {
            e.printStackTrace();
        }
        writeSucceed = true;
    }
}
